package com.bridgeintelligent.tag.webserver.security;

import java.io.File;
import java.nio.charset.StandardCharsets;

import org.apache.commons.lang3.StringUtils;
import org.javalite.http.Get;
import org.javalite.http.Http;
import org.javalite.http.Post;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.bridgeintelligent.tag.user.mgmt.pojo.User;
import com.bridgeintelligent.tag.user.mgmt.service.UserMgmtService;
import com.bridgeintelligent.tag.user.query.service.UserQueryService;
import com.bridgeintelligent.tag.webserver.dim.mgmt.api.DimDepartment;
import com.bridgeintelligent.tag.webserver.dim.mgmt.service.department.DepartmentService;
import com.bridgeintelligent.tag.webserver.security.aes.AesUtils;
import com.wayneleo.quickstart.ErrorDefinition;
import com.wayneleo.quickstart.framework.BaseException;
import com.wayneleo.quickstart.framework.ExceptionCode;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@AllArgsConstructor
public class SsoServiceImpl implements SsoService {

    private SsoConfiguration conf;
    private UserQueryService userQueryService;
    private UserMgmtService userMgmtService;
    private DepartmentService departmentService;

    @Transactional
    public SsoLoginData syncUesrData(String authCode, String state) throws Exception {
        SsoToeknData tokenData = fetchToken(authCode);
        log.warn( "======> access token : " + tokenData.getAccess_token() );
        SsoUserDataVo data = fetchSsoUser(tokenData.getAccess_token());
        log.warn( "======> username: {}, department: ", data.getUsername(), data.getDeptname() );
        addNewUser(data);
        return new SsoLoginData().setUsername(data.getUsername())
                .setToken(tokenData.getAccess_token())
                .setRefreshToken(tokenData.getRefresh_token())
                .setExpires(tokenData.getExpires_in());
    }

    private SsoToeknData fetchToken(String code) {
        String ssoServerUri = String.format(SsoConstants.SSO_FETCH_TOKEN_URI,
                conf.getDomain(),
                conf.getPort(),
                conf.getClientId(),
                conf.getClientSecret(),
                code,
                "authorization_code"
        );
        Post post = Http.post(ssoServerUri);
        log.info( "SSO调试-2-2: " + ssoServerUri );
        String text = post.text(StandardCharsets.UTF_8.name());
        log.info( "SSO调试-2-3: " + text );
        return JacksonHelper.toBean(text, SsoToeknData.class);
    }

    private SsoUserDataVo fetchSsoUser(String token) {
        String ssoServerUri = String.format(SsoConstants.SSO_FETCH_USER_URI,
                conf.getDomain(),
                conf.getPort(),
                conf.getContextPath());
        String tokenKV = "access_token=" + token;
        String clientKV = "client_id=" + conf.getClientId();
        log.info( "SSO调试-2-4: " + ssoServerUri + "?" + tokenKV + "&" + clientKV );
        Get get = Http.get(ssoServerUri + "?" + tokenKV + "&" + clientKV);
        String text = get.text(StandardCharsets.UTF_8.name());
        log.info( "SSO调试-2-5: " + text );
        SsoUserData data = JacksonHelper.toBean(text, SsoUserData.class);
        String username = (data.getSpRoleList() != null) && (!data.getSpRoleList().isEmpty())
                ? data.getSpRoleList().get(0)
                : null;
        String deptname = StringUtils.isNotBlank(data.getOrgNamePath())
                ? new File(data.getOrgNamePath()).getName()
                : null;
        if (!StringUtils.isAnyBlank(username, deptname)) {
            return new SsoUserDataVo().setUsername(username).setDeptname(deptname);
        }
        throw new SsoException(new ErrorDefinition(999, "用户没有权限登录本系统"));
    }

    /**
     * 因为用户管理的逻辑写在了controller层，所以在这里将其代码复制过来
     * from UserMgmtController.addUser(User user, HttpServletRequest request)
     * 
     * @param username 用户名，用户名与用户ID相同
     * @throws Exception
     */
    private void addNewUser(SsoUserDataVo data) throws Exception {
        String username = data.getUsername();
        String deptname = data.getDeptname();
        if (userQueryService.findByUserId(username) != null) {
            return;
        }
        DimDepartment dept = departmentService.fetchByName(deptname);
        if ( dept == null ) {
            throw new BaseException(new ExceptionCode(999, "部门不存在: " + deptname));
        }
        User user = new User(username, username);
        user.setPassword(AesUtils.aesEncrypt(SsoConstants.PASSWORD, AesUtils.AES_KEY));
        user.setName(username);
        user.setEfftctiveSymbol("01");
        // user.setRoleId("4CFA8A2B75324CBA972B2BA0BCD4FD98,1FB61720B9C243F2AC97E52B30B454B4");
        user.setRoleId("882B539B81B34078934CF9DBB68E76B2");
        user.setDepartment(dept.getId() );
        if (!userMgmtService.addUser(user)) {
            throw new SsoException(new ErrorDefinition(999, "添加用户(" + username + ")失败"));
        }
    }

}
